/*
 *
 * Copyright (c) 2001-2017 泛微软件.
 * 泛微协同商务系统,版权所有.
 * 
 */
package com.weaver.integration.ldap.sync.oa;

import com.alibaba.fastjson.JSONObject;
import com.api.integration.ldap.bean.*;
import com.api.integration.ldap.constant.LdapConstant;
import com.api.integration.ldap.enums.LdapEnum;
import com.api.integration.ldap.service.LdapService;
import com.api.integration.ldap.util.MappingType;
import com.api.integration.ldap.util.SyncType;
import com.api.integration.util.RecordSetObj;
import com.engine.integration.constant.LdapSql;
import com.weaver.integration.ldap.exception.LdapException;
import com.weaver.integration.ldap.sync.DataBean;
import com.weaver.integration.ldap.sync.LdapSyncState;
import com.weaver.integration.ldap.sync.formart.OaFormart;
import com.weaver.integration.ldap.util.*;
import weaver.general.TimeUtil;
import weaver.general.Util;
import weaver.hrm.resource.ResourceComInfo;
import weaver.integration.logging.Logger;
import weaver.integration.logging.LoggerFactory;

import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <p>Title: ${file_name}</p>
 * <p>Description:LDAP反向同步处理类  </p>
 *
 * @author SJZ
 * @version 1.0
 * @date 2017/8/2
 */
public class OaSync implements Runnable {

    /**
     * 是否是定时同步
     */
    private boolean isAuto = Boolean.FALSE;

    /**
     * 日志组件
     */
    private final Logger log = LoggerFactory.getLogger(OaSync.class);

    /**
     * 同步节点(按上下级排序)
     */
    private List<LdapSyncBean> baseDNList;

    /**
     * 同步日志文件名称
     */
    private final String LOG_FILE_NAME;

    /**
     * LDAP 标识
     */
    private String ldapId;
    /**
     * LDAP连接配置信息
     */
    private LdapBaseBean ldapBase;

    /**
     * 分部映射列表
     */
    private List<LdapMappingBean> subcompanyMapping;

    /**
     * 部门映射列表
     */
    private List<LdapMappingBean> departmentMapping;

    /**
     * 人员映射列表
     */
    private List<LdapMappingBean> userMapping;

    /**
     * 部门、分部人员对应关系映射列表
     */
    private List<LdapMappingBean> ouMapping;

    /**
     * 同步开始日期
     */
    private String syncDate;

    /**
     * 配置的节点同步后放入该Map中，防止重复同步
     */
    private Map<String, String> lockSync;

    /**
     * Ldap 操作
     */
    private LdapOper ldapOper;

    /**
     * 同步详情记录
     */
    private SyncFileUtil logFile;

    /**
     * 执行状态
     */
    private Boolean runStatus;

    /**
     * 最后同步时间
     */
    private String lastSyncDate;

    /**
     * 同步日志处理
     */
    private LdapSyncLogs ldapSyncLogs;

    /**
     * 开始时间
     */
    private String startTime;

    /**
     * 是否定时
     * @return
     */
    public boolean isAuto() {
        return isAuto;
    }

    public void setAuto( boolean auto ) {
        isAuto = auto;
    }

    /**
     * 构造方法
     * @param ldapId
     * @param syncDate
     */
    public OaSync( String ldapId, String syncDate ) {

        this.ldapId = ldapId;

        this.syncDate = syncDate;

        this.lastSyncDate = TimeUtil.getCurrentDateString();

        this.startTime = TimeUtil.getCurrentTimeString();

        LOG_FILE_NAME = LdapConstant.LDAP_LOG_FILE_PATH + File.separator +
                ldapId + File.separator + new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss-SSS").format(new Date()) + "_OA2LDAP" + ".log";
    }

    /**
     * 服务初始化
     */
    private void init() {

        try {

            logFile = new SyncFileUtil(LOG_FILE_NAME);

        if(this.isAuto()){
            logFile.writeStringToFile("本次同步由定时任务发起@|@${389785}");
        }

        LdapService ldapService = new LdapService(null);

        // 获取LDAP连接配置信息
        ldapBase = ldapService.queryByLdapId(ldapId);
        if (ldapBase == null) {
            logFile.writeStringToFile("未找到对应的LDAP配置@|@${389335}");
            throw new LdapException(String.format("未找到对应的LDAP配置(%s)", ldapId));

        } else if(1 != ldapBase.getIsUsed() || (this.isAuto() && 1 != ldapBase.getIsPush())){
            logFile.writeStringToFile("LDAP或反向同步未启用@|@LDAP、${131272}${32386}");
            throw new LdapException(String.format("LDAP或反向同步未启用(%s)", ldapId));
        }

        //Ldap 连接初始化
        ldapOper = new LdapSuperOper(ldapBase);

        //获取配置的同步节点，按上下级排序
        baseDNList = ldapService.querySyncByLdapId(ldapId, LdapConstant.LDAP_SYNC_PUSH);

        if(baseDNList == null || baseDNList.isEmpty()){
            logFile.writeStringToFile("未找到同步节点配置@|@${389336}");
            throw new LdapException(String.format("未找到对应的同步节点配置(%s)", ldapId));
        }

        //获取人员、部门、分部映射关系列表
        ouMapping = ldapService.queryMappingByLdapId(ldapId, MappingType.OAOU);
        //获取分部对应关系映射列表
        subcompanyMapping = ldapService.queryMappingByLdapId(ldapId, MappingType.OASUBCOMPANY);
        //获取部门对应关系映射列表
        departmentMapping = ldapService.queryMappingByLdapId(ldapId, MappingType.OADEPARTMENT);
        //获取人员对应关系映射列表
        userMapping = ldapService.queryMappingByLdapId(ldapId, MappingType.OAUSER);

        if((subcompanyMapping == null  || subcompanyMapping.isEmpty())
                && (departmentMapping == null || departmentMapping.isEmpty())
                && (userMapping == null || userMapping.isEmpty())){
            logFile.writeStringToFile("未找到字段对应设置@|@${389337}");
            throw new LdapException(String.format("未找到对应的数据映射配置(%s)", ldapId));
        }

            lockSync = new HashMap<String, String>();
        }catch(Exception e){
            log.error("",e);
        }

    }

    /**
     * 服务结束清理
     */
    private void destroy() {
        if (logFile != null) {
            logFile.writeStringToFile("同步完成@|@${129223}");
        }

        //更新定时同步时间
        if(this.isAuto) {
            RecordSetObj rs = new RecordSetObj();
            rs.executeUpdate(LdapSql.UPDATE_LASTSYNCDATE,this.lastSyncDate,this.ldapId,LdapConstant.LDAP_SYNC_PUSH);
        }
    }

    /**
     * 执行
     */
    public void run() {
        //禁止同一时间重复同步相同的Ldap
        log.error("创建文件路径：" + LOG_FILE_NAME+",ldapId:"+ldapId);
        runStatus = LdapSyncState.runSync(ldapId, LdapSyncState.RunType.PUSH, LOG_FILE_NAME);
        log.error("runStatus>>>>>"+runStatus);
        if (!runStatus) {
            log.error("已经有AD同步在运行，ldapId:"+ldapId);
            return;
        }

        ldapSyncLogs = new LdapSyncLogs();
        try {
            //初始化，同步准备
            init();

            LdapSyncBean syncBean;
            Iterator<LdapSyncBean> iter = baseDNList.iterator();
            while (iter.hasNext()) {
                syncBean = iter.next();

                iter.remove();
                lockSync.put(syncBean.getSubcompanyId() + "$_$" + null2Zero(syncBean.getDepartmentId()), "0");

                String str = syncBean.getSubcompanyIdspan();
                if (!"0".equals(null2Zero(syncBean.getDepartmentId()))) {
                    str += " > " + syncBean.getSubcompanyIdspan();
                }

                logFile.writeStringToFile("======================================================");
                logFile.writeStringToFile("开始同步节点@|@${389340}:" + str);
                logFile.writeStringToFile("======================================================");
                if (1 == syncBean.getSyncOrg()) {
                    syncOneOrg(syncBean);
                } else {
                    logFile.writeStringToFile("同步组织结构未开启，跳过@|@${389341}");
                }

                //同步下级组织架构、人员数据
                if (1 == syncBean.getSyncOrg() || 1 == syncBean.getSyncUser()) {
                    syncOrg(syncBean.clone());
                }
            }

            //结束，清理数据
            destroy();
            // 同步成功
            ldapSyncLogs.setSyncStatus(LdapEnum.LDAP_SYNC_RESULT_SUCCESS.getValue());
        } catch (Exception e) {
            log.error(e);
            e.printStackTrace();
            if(logFile != null) {
                logFile.writeStringToFile("同步发生异常已停止，请查看系统日志@|@${389343}");
            }
            // 同步失败
            ldapSyncLogs.setSyncStatus(LdapEnum.LDAP_SYNC_RESULT_FRIL.getValue());

        } finally {
            if(runStatus) {
                LdapSyncState.closeSync(ldapId);
            }

            if (ldapOper != null) {
                ldapOper.close();
            }

            if(logFile != null){
                logFile.close();
            }

            // 将日志维护在表中
            ldapSyncLogs.setLdapId(ldapId);
            ldapSyncLogs.setSyncType(LdapEnum.LDAP_SYNC_TYPE_REVERSE.getValue());
            ldapSyncLogs.setStartTime(startTime);
            String endTime = TimeUtil.getCurrentTimeString();
            ldapSyncLogs.setEndTime(endTime);
            // 同步方式
            if(this.isAuto){
                ldapSyncLogs.setSyncMode(LdapEnum.LDAP_SYNC_MODE_TIMING.getValue());
            }else{
                ldapSyncLogs.setSyncMode(LdapEnum.LDAP_SYNC_MODE_MANUAL.getValue());
            }
            // 文件名
            ldapSyncLogs.setFileName(LOG_FILE_NAME);
            // 运行时间
            String runTime = TimeUtil.timeInterval(startTime,endTime)+"";
            ldapSyncLogs.setRunTime(runTime);
            LdapTool.saveSyncLog(ldapSyncLogs);
        }
    }


    /**
     * 同步第一级组织结构
     *
     * @param syncBean 节点配置信息
     */
    public void syncOneOrg( LdapSyncBean syncBean ) {
        RecordSetObj rs = new RecordSetObj();

        //部门ID不存在，代表分部
        if ("0".equals(null2Zero(syncBean.getDepartmentId()))) {
            rs.executeQuery(SqlConstant.SQL_SELECT_SUBCOMPANY, syncBean.getSubcompanyId());

            List<Map<String, String>> orgDataList = rs.getListOfMap();
            Map<String, String> orgData;

            for (int i = 0; i < orgDataList.size(); i++) {
                orgData = orgDataList.get(i);
                saveSubcompany(syncBean, orgData);
            }

        } else {
            rs.executeQuery(SqlConstant.SQL_SELECT_DEPARTMENT, syncBean.getSubcompanyId(), syncBean.getDepartmentId());

            List<Map<String, String>> orgDataList = rs.getListOfMap();
            Map<String, String> orgData;

            for (int i = 0; i < orgDataList.size(); i++) {
                orgData = orgDataList.get(i);
                saveDepartment(syncBean, orgData);
            }
        }
    }

    /**
     * 同步下级组织结构
     *
     * @param syncBean 节点配置信息
     */
    public void syncOrg( LdapSyncBean syncBean ) {
        LdapSyncBean tempSyncBean;

        RecordSetObj rs = new RecordSetObj();
        //同步下级分部
        if ("0".equals(null2Zero(syncBean.getDepartmentId()))) {
            rs.executeQuery(SqlConstant.SQL_SELECT_CHILD_SUBCOMPANY, syncBean.getSubcompanyId());

            List<Map<String, String>> orgDataList = rs.getListOfMap();
            Map<String, String> orgData;

            for (int i = 0; i < orgDataList.size(); i++) {

                orgData = orgDataList.get(i);

                String key = orgData.get("id") + "$_$0";
                if (isConfig(key)) {
                    continue;
                } else if (lockSync.get(key) != null) {
                    continue;
                }

                //检测该节点是否已配置,避免重复同步
                tempSyncBean = syncBean.clone();
                tempSyncBean.setSubcompanyId(orgData.get("id"));
                tempSyncBean.setDepartmentId("0");

                //同步组织结构开启时，保存分部
                if (1 == tempSyncBean.getSyncOrg()) {
                    saveSubcompany(tempSyncBean, orgData);
                }

                if (1 == tempSyncBean.getSyncOrg() || 1 == tempSyncBean.getSyncUser()) {
                    syncOrg(tempSyncBean.clone());
                }
            }
            //同步人员
        } else {
            if (1 == syncBean.getSyncUser()) {
                syncUser(syncBean.clone());
            }
        }

        //同步下级部门
        if ("0".equals(null2Zero(syncBean.getDepartmentId()))) {
            rs.executeQuery(SqlConstant.SQL_SELECT_TOP_DEPARTMENT, syncBean.getSubcompanyId());
        } else {
            rs.executeQuery(SqlConstant.SQL_SELECT_CHILD_DEPARTMENT, syncBean.getSubcompanyId(), syncBean.getDepartmentId());
        }
        List<Map<String, String>> orgDataList = rs.getListOfMap();
        Map<String, String> orgData;

        for (int i = 0; i < orgDataList.size(); i++) {
            orgData = orgDataList.get(i);

            String key = orgData.get("subcompanyid1") + "$_$" + orgData.get("id");

            if (isConfig(key)) {
                continue;
            } else if (lockSync.get(key) != null) {
                continue;
            }

            if (lockSync.get(key) != null || isConfig(key)) {
                continue;
            }

            //检测该节点是否已配置,避免重复同步
            tempSyncBean = syncBean.clone();
            tempSyncBean.setDepartmentId(orgData.get("id"));
            tempSyncBean.setSubcompanyId(orgData.get("subcompanyid1"));

            if (1 == tempSyncBean.getSyncOrg()) {
                saveDepartment(tempSyncBean, orgData);
            }

            if (1 == tempSyncBean.getSyncOrg() || 1 == tempSyncBean.getSyncUser()) {

                syncOrg(tempSyncBean.clone());
            }
        }
    }

    /**
     * 是否配置了同步节点
     * @param key
     * @return
     */
    private boolean isConfig( String key ) {
        LdapSyncBean tempSyncBean;
        for (int i = 0; i < baseDNList.size(); i++) {
            tempSyncBean = baseDNList.get(i);

            String tempKey = tempSyncBean.getSubcompanyId() + "$_$" + null2Zero(tempSyncBean.getDepartmentId());

            if (tempKey.equalsIgnoreCase(key)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * 同步用户
     *
     * @param syncBean 节点配置信息
     */
    public void syncUser( LdapSyncBean syncBean ) {
        RecordSetObj rs = new RecordSetObj();
        if (syncDate != null && !syncDate.isEmpty()) {
            rs.executeQuery(SqlConstant.SQL_SELECT_USER_OF_DATE, syncBean.getSubcompanyId(), syncBean.getDepartmentId(), syncDate);
        } else {
            rs.executeQuery(SqlConstant.SQL_SELECT_USER, syncBean.getSubcompanyId(), syncBean.getDepartmentId());
        }

        List<Map<String, String>> userDataList = rs.getListOfMap();
        Map<String, String> userData;

        for (int i = 0; i < userDataList.size(); i++) {
            userData = userDataList.get(i);
            logFile.writeStringToFile("同步人员@|@${81793}：" + userData.get("lastname"));
            saveUser(syncBean, userData);
        }
    }

    /**
     * 保存分部
     *
     * @param syncBean 节点配置信息
     * @param orgData  节点数据
     */
    public void saveSubcompany( LdapSyncBean syncBean, Map<String, String> orgData ) {

        String modifyDate = orgData.get("MODIFYDATE");
        if (modifyDate != null && modifyDate.isEmpty() && syncDate != null && !syncDate.isEmpty()) {
            if (DateUtil.compare(modifyDate, syncDate) < 0) {
                return;
            }

        }
        logFile.writeStringToFile("同步分部@|@${32333}：" + orgData.get("subcompanyname"));

        String subKey = "";
        String subValue = "";
        String subClass = "";
        LdapMappingBean mappingBean;
        for (int i = 0; i < ouMapping.size(); i++) {
            mappingBean = ouMapping.get(i);
            if ("subkey".equalsIgnoreCase(mappingBean.getAttributeName())) {
                subKey = mappingBean.getAttributeValue();

            } else if ("subvalue".equalsIgnoreCase(mappingBean.getAttributeName())) {
                subValue = orgData.get(mappingBean.getAttributeValue());

            } else if ("subClass".equalsIgnoreCase(mappingBean.getAttributeName())) {
                subClass = mappingBean.getAttributeValue();
            }
        }
        String dn = subKey + "=" + subValue + "," + syncBean.getBaseDomain();

        LdapService ldapService = new LdapService(null);
        String oaid = orgData.get("id");
        LdapSyncDataBean syncDataBean = ldapService.getSyncDataByOAID(ldapId, oaid, "1", "2");


        boolean dnExist = ldapOper.isExist(dn);

        if (syncDataBean != null && !dnExist) {
           if (!dn.equalsIgnoreCase(syncDataBean.getRdn()) && ldapOper.isExist(syncDataBean.getRdn())) {
                //移动失败新增处理

                dnExist = ldapOper.rename(syncDataBean.getRdn(), dn);
                if(dnExist){
                    String sqltemp="update ldap_sync_data set RDN = replace(RDN,',"+syncDataBean.getRdn()+"',',"+dn+"') where ldapId = ? and syncType = '2' and rdn like '%,"+syncDataBean.getRdn()+"'";
                    RecordSetObj rs = new RecordSetObj();
                    rs.executeUpdate(sqltemp,syncDataBean.getLdapId());
                }
            }
        }

        boolean bool;
        if (dnExist) {
            bool = ldapOper.modify(dn, dataMapping(orgData, subcompanyMapping));
        } else {
            String[] subClassAry = subClass.split(";");
            bool = ldapOper.add(dn, subClassAry, dataMapping(orgData, subcompanyMapping));
        }

        if (!bool) {
            logFile.writeStringToFile("同步失败，请查看系统日志@|@${389348}");
        } else {
            //保存同步对应关系
            syncDataBean = new LdapSyncDataBean();
            syncDataBean.setLdapId(ldapId);
            syncDataBean.setOaId(oaid);
            syncDataBean.setSyncType("2");
            syncDataBean.setDataType("1");
            syncDataBean.setRdn(dn);
            syncDataBean.setUuid(ldapOper.getId(dn));
            ldapService.saveSyncData(syncDataBean);
        }
        syncBean.setBaseDomain(dn);

    }

    /**
     * 保存部门
     *
     * @param syncBean 节点配置信息
     * @param orgData  节点数据
     */
    public void saveDepartment( LdapSyncBean syncBean, Map<String, String> orgData ) {

        String modifyDate = orgData.get("MODIFYDATE");
        if (modifyDate != null && modifyDate.isEmpty() && syncDate != null && !syncDate.isEmpty()) {
            if (DateUtil.compare(modifyDate, syncDate) < 0) {
                return;
            }
        }
        logFile.writeStringToFile("同步部门@|@${32334}：" + orgData.get("departmentname"));

        String depKey = "";
        String depValue = "";
        String depClass = "";
        LdapMappingBean mappingBean;
        for (int i = 0; i < ouMapping.size(); i++) {
            mappingBean = ouMapping.get(i);
            if ("depkey".equalsIgnoreCase(mappingBean.getAttributeName())) {
                depKey = mappingBean.getAttributeValue();

            } else if ("depvalue".equalsIgnoreCase(mappingBean.getAttributeName())) {
                depValue = orgData.get(mappingBean.getAttributeValue());

            } else if ("depClass".equalsIgnoreCase(mappingBean.getAttributeName())) {
                depClass = mappingBean.getAttributeValue();
            }
        }
        String dn = depKey + "=" + depValue + "," + syncBean.getBaseDomain();

        LdapService ldapService = new LdapService(null);
        String oaid = orgData.get("id");
        LdapSyncDataBean syncDataBean = ldapService.getSyncDataByOAID(ldapId, oaid, "2", "2");

        boolean dnExist = ldapOper.isExist(dn);
        if (syncDataBean != null && !dnExist) {
            if (!dn.equalsIgnoreCase(syncDataBean.getRdn()) && ldapOper.isExist(syncDataBean.getRdn())) {
                //移动失败新增处理
                dnExist = ldapOper.rename(syncDataBean.getRdn(), dn);
                if(dnExist) {
                    String sqltemp = "update ldap_sync_data set RDN = replace(RDN,'," + syncDataBean.getRdn() + "','," + dn + "') where ldapId = ? and syncType = '2' and rdn like '%," + syncDataBean.getRdn() + "'";
                    RecordSetObj rs = new RecordSetObj();
                    rs.executeUpdate(sqltemp, syncDataBean.getLdapId());
                }
            }
        }

        boolean bool;
        if (dnExist) {
            bool = ldapOper.modify(dn, dataMapping(orgData, departmentMapping));
        } else {
            String[] depClassAry = depClass.split(";");
            bool = ldapOper.add(dn, depClassAry, dataMapping(orgData, departmentMapping));
        }
        if (!bool) {
            logFile.writeStringToFile("同步失败，请查看系统日志@|@${389348}");
        } else {
            //保存同步对应关系
            syncDataBean = new LdapSyncDataBean();
            syncDataBean.setLdapId(ldapId);
            syncDataBean.setOaId(oaid);
            syncDataBean.setSyncType("2");
            syncDataBean.setDataType("2");
            syncDataBean.setRdn(dn);
            syncDataBean.setUuid(ldapOper.getId(dn));
            ldapService.saveSyncData(syncDataBean);

        }
        syncBean.setBaseDomain(dn);
    }

    /**
     * 保存用户
     *
     * @param syncBean 节点配置信息
     * @param userData 节点数据
     */
    public void saveUser( LdapSyncBean syncBean, Map<String, String> userData ) {
        String userKey = "";
        String userValue = "";
        String userClass = "";
        LdapMappingBean mappingBean;
        for (int i = 0; i < ouMapping.size(); i++) {
            mappingBean = ouMapping.get(i);
            if ("userkey".equalsIgnoreCase(mappingBean.getAttributeName())) {
                userKey = mappingBean.getAttributeValue();

            } else if ("uservalue".equalsIgnoreCase(mappingBean.getAttributeName())) {
                userValue = userData.get(mappingBean.getAttributeValue());

            } else if ("userClass".equalsIgnoreCase(mappingBean.getAttributeName())) {
                userClass = mappingBean.getAttributeValue();
            }
        }
        String dn = userKey + "=" + userValue + "," + syncBean.getBaseDomain();

        LdapService ldapService = new LdapService(null);
        String oaid = userData.get("id");
        LdapSyncDataBean syncDataBean = ldapService.getSyncDataByOAID(ldapId, oaid, "3", "2");
        boolean isneedClear=false;
        //cn配置为帐号时，离职时，帐号会清空。
        if(userValue==null||userValue.equals("")) { //配置的没有关键字cn，
            if( syncDataBean==null||syncDataBean.getRdn()==null|| syncDataBean.getRdn().equals("")) { //并且也没有反向同步记录。这部分数据无效，不同步 ，直接跳转
                log.error("人员id为:" + oaid + ",已经离职过了，以后同步不做处理。");
                 return ;
            }
            dn = syncDataBean.getRdn();
            isneedClear=true;

        }

        boolean dnExist = ldapOper.isExist(dn);
        if (syncDataBean != null && !dnExist) {
            if (!dn.equalsIgnoreCase(syncDataBean.getRdn()) && ldapOper.isExist(syncDataBean.getRdn())) {
                //移动失败新增处理
                dnExist = ldapOper.rename(syncDataBean.getRdn(), dn);
            }
        }
        boolean bool;
        if (dnExist) {
            bool = ldapOper.modify(dn, dataMapping(userData, userMapping));
        } else {
            String loginid = Util.null2String((String)userData.get("loginid"));
            String status = Util.null2String((String)userData.get("status"));
            if ("".equals(loginid) || "5".equals(status)) {
                this.log.error("人员:" + dn + ",帐号为空或已离职，不做同步!");
                this.logFile.writeStringToFile("人员:" + dn + ",帐号为空或已离职，不做同步!");
                return;
            }
            String[] userClassAry = userClass.split(";");
            bool = ldapOper.add(dn, userClassAry, dataMapping(userData, userMapping));
        }
        if (!bool) {
            logFile.writeStringToFile("同步失败，请查看系统日志@|@${389348}");
        } else {

            if(isneedClear) {
                String sql = "DELETE FROM LDAP_SYNC_DATA WHERE LDAPID = ? AND OAID = ?  AND DATATYPE = ? AND SYNCTYPE = ?";
                RecordSetObj rs = new RecordSetObj();
                boolean bool1 = rs.executeUpdate(sql, ldapId, oaid, "3", "2");
                log.error("人员id为:" + oaid + ",离职操作反向同步时清LDAP_SYNC_DATA表里记录。");
            }else {
                //保存同步对应关系
                syncDataBean = new LdapSyncDataBean();
                syncDataBean.setLdapId(ldapId);
                syncDataBean.setOaId(oaid);
                syncDataBean.setSyncType("2");
                syncDataBean.setDataType("3");
                syncDataBean.setRdn(dn);
                syncDataBean.setUuid(ldapOper.getId(dn));
                ldapService.saveSyncData(syncDataBean);
            }
        }
    }

    /**
     * 数据映射
     * @param dataMap
     * @param mapping
     * @return
     */
    private List<DataBean> dataMapping( Map<String, String> dataMap, List<LdapMappingBean> mapping ) {
        List<DataBean> data = new ArrayList<>();

        DataBean dataBean;

        if (mapping != null && dataMap != null) {
            for (int i = 0; i < mapping.size(); i++) {
                LdapMappingBean mappingBean = mapping.get(i);
                dataBean = new DataBean();

                if ("0".equals(mappingBean.getAttributeType())) {
                    //OA 对应值
                    dataBean.setAttrName(mappingBean.getAttributeName());
                    dataBean.setAttrValue(dataMap.get(mappingBean.getAttributeValue()));
                    dataBean.transOperToType(mappingBean.getAttributeOperation());
                    data.add(dataBean);

                } else if ("1".equals(mappingBean.getAttributeType())) {
                    // 固定值
                    dataBean.setAttrName(mappingBean.getAttributeName());
                    dataBean.setAttrValue(mappingBean.getAttributeValue());
                    //固定值只在新增时有效，编辑时不修改
                    //dataBean.restrictEdit();
                    dataBean.transOperToType(mappingBean.getAttributeOperation());
                    data.add(dataBean);

                } else if ("2".equals(mappingBean.getAttributeType())) {
                    /*
                     * TODO_JZ
                     * 2017/7/26
                     * 各个调用的地方应可以设置单独的配置信息。
                     * 将接口注册与接口配置分开。
                     */
                    //调用方法
                    try {
                        LdapFormartBean ldapFormartBean = getFormart(mappingBean.getAttributeValue());
                        if (ldapFormartBean != null) {
                            OaFormart OaFormart = (OaFormart) Class.forName(ldapFormartBean.getFormartClass()).newInstance();

                            Object ret = OaFormart.formart(ldapBase.clone(), dataMap, ldapFormartBean.getFormartParams());
                            if (OaFormart.getStatus()) {
                                dataBean.setAttrName(mappingBean.getAttributeName());
                                dataBean.setAttrValue(ret);
                                dataBean.transOperToType(mappingBean.getAttributeOperation());
                                data.add(dataBean);
                            }
                        }
                    } catch (Exception e) {
                        log.error(e);
                        e.printStackTrace();
                    }
                }
            }
        }
        return data;
    }

    /**
     * NULL 值转换
     *
     * @param id
     * @return NULL Empty 返回 0，其它返回原值
     */
    private String null2Zero( String id ) {
        if (id == null || id.isEmpty()) {
            id = "0";
        }
        return id;
    }

    /**
     * 获取格式化配置
     *
     * @param formartId 标识
     * @return
     */
    private LdapFormartBean getFormart( String formartId ) {
        String sql = "select * from ldap_formart where formartId = ? ";
        RecordSetObj rs = new RecordSetObj();
        rs.executeQuery(sql, formartId);

        LdapFormartBean ldapFormartBean = null;
        if (rs.next()) {
            ldapFormartBean = rs.getBean(LdapFormartBean.class);
        }
        return ldapFormartBean;
    }

    /**
     *  修改ad密码
     * @param dataMap,dadaMap里需要至少有三个参数.userid oa里人员id,loginid 人员帐号,password 人员密码
     * @return
     */
    public boolean  modifyADPWD( Map<String, String> dataMap) {

        String userid= Util.null2String(dataMap.get("userid"));
        String loginid= Util.null2String(dataMap.get("loginid"));
        String password= Util.null2String(dataMap.get("password"));
        String oldPassword=Util.null2String(dataMap.get("oldPassword"));
        String issysadmin=Util.null2String(dataMap.get("issysadmin"));
        log.error("修改AD密码>>>>>>>>>>>帐号："+loginid+",issysadmin=>>"+issysadmin);
        LdapBaseBean baseBean=null;
        String rdn="";

        if(!issysadmin.equalsIgnoreCase("true")&&oldPassword.equals("")){
            log.error("原密码为空！");
            return false;
        }
        if(!issysadmin.equals("1")&&!oldPassword.equals("")){
            AuthenticUtil authenticUtil=new AuthenticUtil();
            if(!authenticUtil.checkLogin(loginid,oldPassword).equals("100")){
                log.error("原密码验证失败！");
                return false;
            }
        }


        if(this.ldapId==null||this.ldapId.equals("")){
            try {

                LdapService ldapService = new LdapService(null);
                ResourceComInfo rc = new ResourceComInfo();
                String oaUid = rc.getUserIdByLoginId(loginid);

                LdapSyncDataBean userDatas = null;
                RecordSetObj rs = new RecordSetObj();

                boolean bool = rs.executeQuery(LdapSql.SELECT_LOGIN_SYNC_DATA, oaUid, 3);
                if (bool && rs.next()) {
                    userDatas = rs.getBean(LdapSyncDataBean.class);
                }


                if (null == userDatas) {
                    bool = rs.executeQuery(LdapSql.SELECT_ALL_ACTIVE);
                    if (bool && rs.next()) {
                        baseBean = rs.getBean(LdapBaseBean.class);
                    } else {
                        log.error("无可用LDAP配置");
                        return false;
                    }
                } else {
                    rdn = userDatas.getRdn();
                    String ldapId = userDatas.getLdapId();
                    baseBean = ldapService.queryByLdapId(ldapId);
                }
                if (baseBean == null) {
                    log.error(String.format("未找到对应的LDAP配置(%s)", loginid));
                    return false;
                } else if (baseBean.getIsUsed() == 0) {
                    log.error(String.format("Ldap未开启(%s)", baseBean.getLdapId()));
                    return false;
                } else if (baseBean.getIsAdAccount() == 0) {
                    log.error(String.format("LDAP登录认证未启用(%s)", baseBean.getLdapId()));
                    return false;
                }
            }catch (Exception e){
                log.error("修改AD密码获取连接信息错误！",e);
                return  false;
            }
            LdapService ldapService = new LdapService(null);
            List<LdapSyncBean> baseDNList = ldapService.querySyncByLdapIdOrderDN(ldapId);
            LdapSuperOper  adminOper = new LdapSuperOper(baseBean);

            if(rdn.equals("")){
                rdn=getRdn(loginid,baseBean);
            }

            LdapSyncBean syncBean;
            Iterator<LdapSyncBean> iter = baseDNList.iterator();
            Map<String, Object> data=new HashMap<String,Object>() ;

       ;

            String newQuotedPassword = "\"" + password +"\"";
            try {
                byte[] newUnicodePassword =newQuotedPassword.getBytes("UTF-16LE");
                data.put("unicodePwd",newUnicodePassword);
            } catch (UnsupportedEncodingException e) {
                log.error("处理AD失败！",e);
                e.printStackTrace();
            }
            //while (iter.hasNext()) {
               // syncBean = iter.next();
               if(adminOper.modifyArrts(rdn,data)){
                   return true;
               }
            //}
    }
        return false;
    }



    /**
     * 获取RDN信息
     * @param loginid
     * @param baseBean
     * @return
     */
    public  String getRdn(String loginid,  LdapBaseBean baseBean){

        String dn = "";
		/*
		 * TODO_JZ
		 * 2018/11/19
		 * 后期改进
		 */

        // 获取loginid 对应的 LDAP属性
        RecordSetObj rs = new RecordSetObj();
        boolean bool = rs.executeQuery(LdapSql.SELECT_MAPPING,baseBean.getLdapId(), MappingType.USER.getValue());
        String loginKey;
        if("ad".equalsIgnoreCase(baseBean.getLdapType())){
            loginKey = "samaccountname";
        }else{
            loginKey = "uid";
        }
        if(bool){
            List<LdapMappingBean> mapList = rs.getListOfBean(LdapMappingBean.class);
            for(LdapMappingBean mappingBean : mapList){
                if("loginid".equalsIgnoreCase(mappingBean.getAttributeName())
                        && "0".equalsIgnoreCase(mappingBean.getAttributeType())){
                    loginKey = mappingBean.getAttributeValue();
                    break;
                }
            }
        }

        bool = rs.executeQuery(LdapSql.SELECT_SYNC,baseBean.getLdapId(), SyncType.PULL.getValue());

        if(bool){
            List<LdapSyncBean> list = rs.getListOfBean(LdapSyncBean.class);

            LdapSuperOper adminOper = new LdapSuperOper(baseBean);

            for(LdapSyncBean syncBean : list){

                String baseDN = "";

                if(1==syncBean.getIsSynByGroup()){ //组同步
                    String[] arr_baseDN = Util.TokenizerString2(syncBean.getBaseDomain().toUpperCase(), ",");
                    for (int i = 0; i < arr_baseDN.length; i++) {
                        if (arr_baseDN[i].indexOf("DC=") < 0)
                            continue;
                        if (!baseDN.equals(""))
                            baseDN = baseDN+"," + arr_baseDN[i];
                        else
                            baseDN += arr_baseDN[i];
                    }
                }
                else{
                    baseDN=syncBean.getBaseDomain();

                }
                List<SearchResult> results = adminOper.searchAll(baseDN,
                        "(&(" + loginKey + "=" + loginid + ")" + syncBean.getUserFilter() + ")",
                        SearchControls.SUBTREE_SCOPE);
                if(results != null && results.size()>0){
                    SearchResult attr = results.get(0);
                    dn = attr.getNameInNamespace();
                    break;
                }
            }
        }
        return dn;
    }

}
